// PonPoff.h: interface for the CPonPoff class.
//
//////////////////////////////////////////////////////////////////////

#ifndef PON_POFF_H
#define PON_POFF_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <math.h>

#include "AClassifier.h"

#define		MAXLLR	1000

class CBin
{
public:
	CBin(){fPon = fPoff = 0;};
	CBin(float fPon1, float fPoff1)
	{
		fPon = fPon1;
		fPoff = fPoff1;
		if (fPon == 0)
			fLLR = -MAXLLR;
		else if (fPoff == 0)
			fLLR = MAXLLR;
		else
			fLLR = log(fPon/fPoff);
	}

	CBin operator=(const CBin &bin)
	{
		fPon  = bin.fPon;
		fPoff = bin.fPoff;
		fLLR  = bin.fLLR;
		return *this;
	}

	float fPon;
	float fPoff;
	float fLLR;  // Log Likelihood ratio
};

typedef std::vector<CBin> vBin;

class CPonPoff : public CAClassifier
{
public:
	void Clear();
	CPonPoff(vfeaid &vfid);
	CPonPoff()
	{
		strcpy(m_strID, "PonPoff");
		m_fT = 1;
		m_p_binindex = NULL;
	};
	CPonPoff(int nDim);
	virtual ~CPonPoff();

	void BuildBins(vfloat &vfPos, vfloat &vfNeg);
	void SetThreshold(float fT) {m_fT = fT;};
	bool Classify(vfloat &vfFeatures, float fT, const char flag);
	bool Classify(vfloat &vfFeatures, const char flag);
	float Classify(CASample *pSample, const char flag);
	bool SaveToFile(const char * strFileName);
	bool LoadFromFile(const char * strFileName);
	void SaveToFile(FILE *fp);
	void LoadFromFile(FILE *fp);

	CPonPoff operator=(const CPonPoff &pp)
	{
		strcpy(m_strID, pp.m_strID);
		m_vFeaID = pp.m_vFeaID;
		m_fT     = pp.m_fT;
		m_nDim   = pp.m_nDim;
		m_vbBins = pp.m_vbBins;
		m_vnBins = pp.m_vnBins;
		m_vfBinBoundaries = pp.m_vfBinBoundaries;
		return *this;
	}

protected:
	float	SumSqrtPonPoff();
	void	FillBins(vfloat &vfPos, vfloat &vfNeg);
	void	CreateIndexTable(void);
	inline	int		GetIndex(const float fvalue, const int i);
	
private:
	int		m_nDim;
	float	m_fT;
	vint	m_vnBins;
	vfloat	m_vfBinBoundaries;
	vBin	m_vbBins;

	vfloat	m_min_values;
	vfloat	m_max_values;
	vfloat	m_delta;
	vint	*m_p_binindex;
};

inline int	CPonPoff::GetIndex(const float fvalue, const int i)
{
	if (fvalue <= m_min_values[i])
		return 0;
	if (fvalue >= m_max_values[i])
		return m_vnBins[i]-1;

	int index=(int)floor((fvalue-m_min_values[i])/m_delta[i]);

	return m_p_binindex[i][index];
}



#endif 
